Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Displaying Raw • Download


RNS/Packet.py de7e0996ce218f5b697c33ff3d64f1451f4a1f0a (de7e0996) Text, 25.12 KB

T8b949e# Reticulum License
T8b949e#
T8b949e# Copyright (c) 2016-2025 Mark Qvist
T8b949e#
T8b949e# Permission is hereby granted, free of charge, to any person obtaining a copy
T8b949e# of this software and associated documentation files (the "Software"), to deal
T8b949e# in the Software without restriction, including without limitation the rights
T8b949e# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
T8b949e# copies of the Software, and to permit persons to whom the Software is
T8b949e# furnished to do so, subject to the following conditions:
T8b949e#
T8b949e# - The Software shall not be used in any kind of system which includes amongst
T8b949e# its functions the ability to purposefully do harm to human beings.
T8b949e#
T8b949e# - The Software shall not be used, directly or indirectly, in the creation of
T8b949e# an artificial intelligence, machine learning or language model training
T8b949e# dataset, including but not limited to any use that contributes to the
T8b949e# training or development of such a model or algorithm.
T8b949e#
T8b949e# - The above copyright notice and this permission notice shall be included in
T8b949e# all copies or substantial portions of the Software.
T8b949e#
T8b949e# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
T8b949e# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
T8b949e# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
T8b949e# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
T8b949e# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
T8b949e# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
T8b949e# SOFTWARE.

Tff7b72import T7ee787threading
Tff7b72import T7ee787struct
Tff7b72import T7ee787math
Tff7b72import T7ee787time
Tff7b72import T7ee787RNS

Tff7b72class T56d364PacketTb4b4b4:
T8b949e"""
The Packet class is used to create packet instances that can be sent
over a Reticulum network. Packets will automatically be encrypted if
they are addressed to a ``RNS.Destination.SINGLE`` destination,
``RNS.Destination.GROUP`` destination or a :ref:`RNS.Link<api-link>`.

For ``RNS.Destination.GROUP`` destinations, Reticulum will use the
pre-shared key configured for the destination. All packets to group
destinations are encrypted with the same AES-256 key.

For ``RNS.Destination.SINGLE`` destinations, Reticulum will use a newly
derived ephemeral AES-256 key for every packet.

For :ref:`RNS.Link<api-link>` destinations, Reticulum will use per-link
ephemeral keys, and offers **Forward Secrecy**.

:param destination: A :ref:`RNS.Destination<api-destination>` instance to which the packet will be sent.
:param data: The data payload to be included in the packet as *bytes*.
:param create_receipt: Specifies whether a :ref:`RNS.PacketReceipt<api-packetreceipt>` should be created when instantiating the packet.
"""

T8b949e# Packet types
Te6edf3DATA Tff7b72= T79c0ff0x00 T8b949e# Data packets
Te6edf3ANNOUNCE Tff7b72= T79c0ff0x01 T8b949e# Announces
Te6edf3LINKREQUEST Tff7b72= T79c0ff0x02 T8b949e# Link requests
Te6edf3PROOF Tff7b72= T79c0ff0x03 T8b949e# Proofs
Te6edf3types Tff7b72= Tb4b4b4[Te6edf3DATATb4b4b4, Te6edf3ANNOUNCETb4b4b4, Te6edf3LINKREQUESTTb4b4b4, Te6edf3PROOFTb4b4b4]

T8b949e# Header types
Te6edf3HEADER_1 Tff7b72= T79c0ff0x00 T8b949e# Normal header format
Te6edf3HEADER_2 Tff7b72= T79c0ff0x01 T8b949e# Header format used for packets in transport
Te6edf3header_types Tff7b72= Tb4b4b4[Te6edf3HEADER_1Tb4b4b4, Te6edf3HEADER_2Tb4b4b4]

T8b949e# Packet context types
Te6edf3NONE Tff7b72= T79c0ff0x00 T8b949e# Generic data packet
Te6edf3RESOURCE Tff7b72= T79c0ff0x01 T8b949e# Packet is part of a resource
Te6edf3RESOURCE_ADV Tff7b72= T79c0ff0x02 T8b949e# Packet is a resource advertisement
Te6edf3RESOURCE_REQ Tff7b72= T79c0ff0x03 T8b949e# Packet is a resource part request
Te6edf3RESOURCE_HMU Tff7b72= T79c0ff0x04 T8b949e# Packet is a resource hashmap update
Te6edf3RESOURCE_PRF Tff7b72= T79c0ff0x05 T8b949e# Packet is a resource proof
Te6edf3RESOURCE_ICL Tff7b72= T79c0ff0x06 T8b949e# Packet is a resource initiator cancel message
Te6edf3RESOURCE_RCL Tff7b72= T79c0ff0x07 T8b949e# Packet is a resource receiver cancel message
Te6edf3CACHE_REQUEST Tff7b72= T79c0ff0x08 T8b949e# Packet is a cache request
Te6edf3REQUEST Tff7b72= T79c0ff0x09 T8b949e# Packet is a request
Te6edf3RESPONSE Tff7b72= T79c0ff0x0A T8b949e# Packet is a response to a request
Te6edf3PATH_RESPONSE Tff7b72= T79c0ff0x0B T8b949e# Packet is a response to a path request
Te6edf3COMMAND Tff7b72= T79c0ff0x0C T8b949e# Packet is a command
Te6edf3COMMAND_STATUS Tff7b72= T79c0ff0x0D T8b949e# Packet is a status of an executed command
Te6edf3CHANNEL Tff7b72= T79c0ff0x0E T8b949e# Packet contains link channel data
Te6edf3KEEPALIVE Tff7b72= T79c0ff0xFA T8b949e# Packet is a keepalive packet
Te6edf3LINKIDENTIFY Tff7b72= T79c0ff0xFB T8b949e# Packet is a link peer identification proof
Te6edf3LINKCLOSE Tff7b72= T79c0ff0xFC T8b949e# Packet is a link close message
Te6edf3LINKPROOF Tff7b72= T79c0ff0xFD T8b949e# Packet is a link packet proof
Te6edf3LRRTT Tff7b72= T79c0ff0xFE T8b949e# Packet is a link request round-trip time measurement
Te6edf3LRPROOF Tff7b72= T79c0ff0xFF T8b949e# Packet is a link request proof

T8b949e# Context flag values
Te6edf3FLAG_SET Tff7b72= T79c0ff0x01
Te6edf3FLAG_UNSET Tff7b72= T79c0ff0x00

T8b949e# This is used to calculate allowable
T8b949e# payload sizes
Te6edf3HEADER_MAXSIZE Tff7b72= Te6edf3RNSTff7b72.Td2a8ffReticulumTff7b72.Td2a8ffHEADER_MAXSIZE
Te6edf3MDU Tff7b72= Te6edf3RNSTff7b72.Td2a8ffReticulumTff7b72.Td2a8ffMDU

T8b949e# With an MTU of 500, the maximum of data we can
T8b949e# send in a single encrypted packet is given by
T8b949e# the below calculation; 383 bytes.
Te6edf3ENCRYPTED_MDU Tff7b72= Te6edf3mathTff7b72.Td2a8fffloorTb4b4b4(Tb4b4b4(Te6edf3RNSTff7b72.Td2a8ffReticulumTff7b72.Td2a8ffMDUTff7b72-Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8ffTOKEN_OVERHEADTff7b72-Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8ffKEYSIZETff7b72/Tff7b72/T79c0ff16Tb4b4b4)Tff7b72/Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8ffAES128_BLOCKSIZETb4b4b4)Tff7b72*Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8ffAES128_BLOCKSIZE Tff7b72- T79c0ff1
T8b949e"""
The maximum size of the payload data in a single encrypted packet
"""
Te6edf3PLAIN_MDU Tff7b72= Te6edf3MDU
T8b949e"""
The maximum size of the payload data in a single unencrypted packet
"""

Te6edf3TIMEOUT_PER_HOP Tff7b72= Te6edf3RNSTff7b72.Td2a8ffReticulumTff7b72.Td2a8ffDEFAULT_PER_HOP_TIMEOUT

Tff7b72__slots__ Tff7b72= Ta5d6ff"Ta5d6ffhopsTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffheaderTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffheader_typeTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffpacket_typeTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fftransport_typeTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffcontextTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffcontext_flagTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffdestinationTa5d6ff"
Tff7b72__slots__ Tff7b72+Tff7b72= Ta5d6ff"Ta5d6fftransport_idTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffdataTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffflagsTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffrawTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffpackedTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffsentTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffcreate_receiptTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffreceiptTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fffromPackedTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffMTUTa5d6ff"
Tff7b72__slots__ Tff7b72+Tff7b72= Ta5d6ff"Ta5d6ffsent_atTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffpacket_hashTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffratchet_idTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffattached_interfaceTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffreceiving_interfaceTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffrssiTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffsnrTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffqTa5d6ff"
Tff7b72__slots__ Tff7b72+Tff7b72= Ta5d6ff"Ta5d6ffciphertextTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffplaintextTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffdestination_hashTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffdestination_typeTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fflinkTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffmap_hashTa5d6ff"

Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3destinationTb4b4b4, Te6edf3dataTb4b4b4, Te6edf3packet_type Tff7b72= Te6edf3DATATb4b4b4, Te6edf3context Tff7b72= Te6edf3NONETb4b4b4, Te6edf3transport_type Tff7b72= Te6edf3RNSTff7b72.Td2a8ffTransportTff7b72.Td2a8ffBROADCASTTb4b4b4,
Te6edf3header_type Tff7b72= Te6edf3HEADER_1Tb4b4b4, Te6edf3transport_id Tff7b72= Tff7b72NoneTb4b4b4, Te6edf3attached_interface Tff7b72= Tff7b72NoneTb4b4b4, Te6edf3create_receipt Tff7b72= Tff7b72TrueTb4b4b4, Te6edf3context_flagTff7b72=Te6edf3FLAG_UNSETTb4b4b4)Tb4b4b4:

Tff7b72if Te6edf3destination Tff7b72!= Tff7b72NoneTb4b4b4:
Tff7b72if Te6edf3transport_type Tff7b72== Tff7b72NoneTb4b4b4:
Te6edf3transport_type Tff7b72= Te6edf3RNSTff7b72.Td2a8ffTransportTff7b72.Td2a8ffBROADCAST

Tff7b72selfTff7b72.Td2a8ffheader_type Tff7b72= Te6edf3header_type
Tff7b72selfTff7b72.Td2a8ffpacket_type Tff7b72= Te6edf3packet_type
Tff7b72selfTff7b72.Td2a8fftransport_type Tff7b72= Te6edf3transport_type
Tff7b72selfTff7b72.Td2a8ffcontext Tff7b72= Te6edf3context
Tff7b72selfTff7b72.Td2a8ffcontext_flag Tff7b72= Te6edf3context_flag

Tff7b72selfTff7b72.Td2a8ffhops Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72selfTff7b72.Td2a8ffdestination Tff7b72= Te6edf3destination
Tff7b72selfTff7b72.Td2a8fftransport_id Tff7b72= Te6edf3transport_id
Tff7b72selfTff7b72.Td2a8ffdata Tff7b72= Te6edf3data
Tff7b72selfTff7b72.Td2a8ffflags Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_packed_flagsTb4b4b4(Tb4b4b4)

Tff7b72selfTff7b72.Td2a8ffraw Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffpacked Tff7b72= Tff7b72False
Tff7b72selfTff7b72.Td2a8ffsent Tff7b72= Tff7b72False
Tff7b72selfTff7b72.Td2a8ffcreate_receipt Tff7b72= Te6edf3create_receipt
Tff7b72selfTff7b72.Td2a8ffreceipt Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8fffromPacked Tff7b72= Tff7b72False
Tff7b72elseTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffraw Tff7b72= Te6edf3data
Tff7b72selfTff7b72.Td2a8ffpacked Tff7b72= Tff7b72True
Tff7b72selfTff7b72.Td2a8fffromPacked Tff7b72= Tff7b72True
Tff7b72selfTff7b72.Td2a8ffcreate_receipt Tff7b72= Tff7b72False

Tff7b72if Te6edf3destination Tff7b72and Te6edf3destinationTff7b72.Td2a8fftype Tff7b72== Te6edf3RNSTff7b72.Td2a8ffDestinationTff7b72.Td2a8ffLINKTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffMTU Tff7b72= Te6edf3destinationTff7b72.Td2a8ffmtu
Tff7b72elseTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffMTU Tff7b72= Te6edf3RNSTff7b72.Td2a8ffReticulumTff7b72.Td2a8ffMTU

Tff7b72selfTff7b72.Td2a8ffsent_at Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffpacket_hash Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffratchet_id Tff7b72= Tff7b72None

Tff7b72selfTff7b72.Td2a8ffattached_interface Tff7b72= Te6edf3attached_interface
Tff7b72selfTff7b72.Td2a8ffreceiving_interface Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffrssi Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffsnr Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffq Tff7b72= Tff7b72None

Tff7b72def Td2a8ffget_packed_flagsTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffcontext Tff7b72== Te6edf3PacketTff7b72.Td2a8ffLRPROOFTb4b4b4:
Te6edf3packed_flags Tff7b72= Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffheader_type Tff7b72<< T79c0ff6Tb4b4b4) Tff7b72| Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffcontext_flag Tff7b72<< T79c0ff5Tb4b4b4) Tff7b72| Tb4b4b4(Tff7b72selfTff7b72.Td2a8fftransport_type Tff7b72<< T79c0ff4Tb4b4b4) Tff7b72| Tb4b4b4(Te6edf3RNSTff7b72.Td2a8ffDestinationTff7b72.Td2a8ffLINK Tff7b72<< T79c0ff2Tb4b4b4) Tff7b72| Tff7b72selfTff7b72.Td2a8ffpacket_type
Tff7b72elseTb4b4b4:
Te6edf3packed_flags Tff7b72= Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffheader_type Tff7b72<< T79c0ff6Tb4b4b4) Tff7b72| Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffcontext_flag Tff7b72<< T79c0ff5Tb4b4b4) Tff7b72| Tb4b4b4(Tff7b72selfTff7b72.Td2a8fftransport_type Tff7b72<< T79c0ff4Tb4b4b4) Tff7b72| Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8fftype Tff7b72<< T79c0ff2Tb4b4b4) Tff7b72| Tff7b72selfTff7b72.Td2a8ffpacket_type

Tff7b72return Te6edf3packed_flags

Tff7b72def Td2a8ffpackTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffdestination_hash Tff7b72= Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffhash
Tff7b72selfTff7b72.Td2a8ffheader Tff7b72= Ta5d6ffbTa5d6ff"Ta5d6ff"
Tff7b72selfTff7b72.Td2a8ffheader Tff7b72+Tff7b72= Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff"Ta5d6ff!BTa5d6ff"Tb4b4b4, Tff7b72selfTff7b72.Td2a8ffflagsTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffheader Tff7b72+Tff7b72= Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff"Ta5d6ff!BTa5d6ff"Tb4b4b4, Tff7b72selfTff7b72.Td2a8ffhopsTb4b4b4)

Tff7b72if Tff7b72selfTff7b72.Td2a8ffcontext Tff7b72== Te6edf3PacketTff7b72.Td2a8ffLRPROOFTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffheader Tff7b72+Tff7b72= Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8fflink_id
Tff7b72selfTff7b72.Td2a8ffciphertext Tff7b72= Tff7b72selfTff7b72.Td2a8ffdata
Tff7b72elseTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffheader_type Tff7b72== Te6edf3PacketTff7b72.Td2a8ffHEADER_1Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffheader Tff7b72+Tff7b72= Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffhash

Tff7b72if Tff7b72selfTff7b72.Td2a8ffpacket_type Tff7b72== Te6edf3PacketTff7b72.Td2a8ffANNOUNCETb4b4b4:
T8b949e# Announce packets are not encrypted
Tff7b72selfTff7b72.Td2a8ffciphertext Tff7b72= Tff7b72selfTff7b72.Td2a8ffdata
Tff7b72elif Tff7b72selfTff7b72.Td2a8ffpacket_type Tff7b72== Te6edf3PacketTff7b72.Td2a8ffLINKREQUESTTb4b4b4:
T8b949e# Link request packets are not encrypted
Tff7b72selfTff7b72.Td2a8ffciphertext Tff7b72= Tff7b72selfTff7b72.Td2a8ffdata
Tff7b72elif Tff7b72selfTff7b72.Td2a8ffpacket_type Tff7b72== Te6edf3PacketTff7b72.Td2a8ffPROOF Tff7b72and Tff7b72selfTff7b72.Td2a8ffcontext Tff7b72== Te6edf3PacketTff7b72.Td2a8ffRESOURCE_PRFTb4b4b4:
T8b949e# Resource proofs are not encrypted
Tff7b72selfTff7b72.Td2a8ffciphertext Tff7b72= Tff7b72selfTff7b72.Td2a8ffdata
Tff7b72elif Tff7b72selfTff7b72.Td2a8ffpacket_type Tff7b72== Te6edf3PacketTff7b72.Td2a8ffPROOF Tff7b72and Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8fftype Tff7b72== Te6edf3RNSTff7b72.Td2a8ffDestinationTff7b72.Td2a8ffLINKTb4b4b4:
T8b949e# Packet proofs over links are not encrypted
Tff7b72selfTff7b72.Td2a8ffciphertext Tff7b72= Tff7b72selfTff7b72.Td2a8ffdata
Tff7b72elif Tff7b72selfTff7b72.Td2a8ffcontext Tff7b72== Te6edf3PacketTff7b72.Td2a8ffRESOURCETb4b4b4:
T8b949e# A resource takes care of encryption
T8b949e# by itself
Tff7b72selfTff7b72.Td2a8ffciphertext Tff7b72= Tff7b72selfTff7b72.Td2a8ffdata
Tff7b72elif Tff7b72selfTff7b72.Td2a8ffcontext Tff7b72== Te6edf3PacketTff7b72.Td2a8ffKEEPALIVETb4b4b4:
T8b949e# Keepalive packets contain no actual
T8b949e# data
Tff7b72selfTff7b72.Td2a8ffciphertext Tff7b72= Tff7b72selfTff7b72.Td2a8ffdata
Tff7b72elif Tff7b72selfTff7b72.Td2a8ffcontext Tff7b72== Te6edf3PacketTff7b72.Td2a8ffCACHE_REQUESTTb4b4b4:
T8b949e# Cache-requests are not encrypted
Tff7b72selfTff7b72.Td2a8ffciphertext Tff7b72= Tff7b72selfTff7b72.Td2a8ffdata
Tff7b72elseTb4b4b4:
T8b949e# In all other cases, we encrypt the packet
T8b949e# with the destination's encryption method
Tff7b72selfTff7b72.Td2a8ffciphertext Tff7b72= Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffencryptTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdataTb4b4b4)
Tff7b72if Tffa657hasattrTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdestinationTb4b4b4, Ta5d6ff"Ta5d6fflatest_ratchet_idTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffratchet_id Tff7b72= Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8fflatest_ratchet_id

Tff7b72if Tff7b72selfTff7b72.Td2a8ffheader_type Tff7b72== Te6edf3PacketTff7b72.Td2a8ffHEADER_2Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8fftransport_id Tff7b72!= Tff7b72NoneTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffheader Tff7b72+Tff7b72= Tff7b72selfTff7b72.Td2a8fftransport_id
Tff7b72selfTff7b72.Td2a8ffheader Tff7b72+Tff7b72= Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffhash

Tff7b72if Tff7b72selfTff7b72.Td2a8ffpacket_type Tff7b72== Te6edf3PacketTff7b72.Td2a8ffANNOUNCETb4b4b4:
T8b949e# Announce packets are not encrypted
Tff7b72selfTff7b72.Td2a8ffciphertext Tff7b72= Tff7b72selfTff7b72.Td2a8ffdata
Tff7b72elseTb4b4b4:
Tff7b72raise Tf85149IOErrorTb4b4b4(Ta5d6ff"Ta5d6ffPacket with header type 2 must have a transport IDTa5d6ff"Tb4b4b4)


Tff7b72selfTff7b72.Td2a8ffheader Tff7b72+Tff7b72= Tffa657bytesTb4b4b4(Tb4b4b4[Tff7b72selfTff7b72.Td2a8ffcontextTb4b4b4]Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffraw Tff7b72= Tff7b72selfTff7b72.Td2a8ffheader Tff7b72+ Tff7b72selfTff7b72.Td2a8ffciphertext

Tff7b72if Tffa657lenTb4b4b4(Tff7b72selfTff7b72.Td2a8ffrawTb4b4b4) Tff7b72> Tff7b72selfTff7b72.Td2a8ffMTUTb4b4b4:
Tff7b72raise Tf85149IOErrorTb4b4b4(Ta5d6ff"Ta5d6ffPacket size of Ta5d6ff"Tff7b72+Tffa657strTb4b4b4(Tffa657lenTb4b4b4(Tff7b72selfTff7b72.Td2a8ffrawTb4b4b4)Tb4b4b4)Tff7b72+Ta5d6ff"Ta5d6ff exceeds MTU of Ta5d6ff"Tff7b72+Tffa657strTb4b4b4(Tff7b72selfTff7b72.Td2a8ffMTUTb4b4b4)Tff7b72+Ta5d6ff"Ta5d6ff bytesTa5d6ff"Tb4b4b4)

Tff7b72selfTff7b72.Td2a8ffpacked Tff7b72= Tff7b72True
Tff7b72selfTff7b72.Td2a8ffupdate_hashTb4b4b4(Tb4b4b4)


Tff7b72def Td2a8ffunpackTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffflags Tff7b72= Tff7b72selfTff7b72.Td2a8ffrawTb4b4b4[T79c0ff0Tb4b4b4]
Tff7b72selfTff7b72.Td2a8ffhops Tff7b72= Tff7b72selfTff7b72.Td2a8ffrawTb4b4b4[T79c0ff1Tb4b4b4]

Tff7b72selfTff7b72.Td2a8ffheader_type Tff7b72= Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffflags Tff7b72& T79c0ff0b01000000Tb4b4b4) Tff7b72>> T79c0ff6
Tff7b72selfTff7b72.Td2a8ffcontext_flag Tff7b72= Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffflags Tff7b72& T79c0ff0b00100000Tb4b4b4) Tff7b72>> T79c0ff5
Tff7b72selfTff7b72.Td2a8fftransport_type Tff7b72= Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffflags Tff7b72& T79c0ff0b00010000Tb4b4b4) Tff7b72>> T79c0ff4
Tff7b72selfTff7b72.Td2a8ffdestination_type Tff7b72= Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffflags Tff7b72& T79c0ff0b00001100Tb4b4b4) Tff7b72>> T79c0ff2
Tff7b72selfTff7b72.Td2a8ffpacket_type Tff7b72= Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffflags Tff7b72& T79c0ff0b00000011Tb4b4b4)

Te6edf3DST_LEN Tff7b72= Te6edf3RNSTff7b72.Td2a8ffReticulumTff7b72.Td2a8ffTRUNCATED_HASHLENGTHTff7b72/Tff7b72/T79c0ff8

Tff7b72if Tff7b72selfTff7b72.Td2a8ffheader_type Tff7b72== Te6edf3PacketTff7b72.Td2a8ffHEADER_2Tb4b4b4:
Tff7b72selfTff7b72.Td2a8fftransport_id Tff7b72= Tff7b72selfTff7b72.Td2a8ffrawTb4b4b4[T79c0ff2Tb4b4b4:Te6edf3DST_LENTff7b72+T79c0ff2Tb4b4b4]
Tff7b72selfTff7b72.Td2a8ffdestination_hash Tff7b72= Tff7b72selfTff7b72.Td2a8ffrawTb4b4b4[Te6edf3DST_LENTff7b72+T79c0ff2Tb4b4b4:T79c0ff2Tff7b72*Te6edf3DST_LENTff7b72+T79c0ff2Tb4b4b4]
Tff7b72selfTff7b72.Td2a8ffcontext Tff7b72= Tffa657ordTb4b4b4(Tff7b72selfTff7b72.Td2a8ffrawTb4b4b4[T79c0ff2Tff7b72*Te6edf3DST_LENTff7b72+T79c0ff2Tb4b4b4:T79c0ff2Tff7b72*Te6edf3DST_LENTff7b72+T79c0ff3Tb4b4b4]Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffdata Tff7b72= Tff7b72selfTff7b72.Td2a8ffrawTb4b4b4[T79c0ff2Tff7b72*Te6edf3DST_LENTff7b72+T79c0ff3Tb4b4b4:Tb4b4b4]
Tff7b72elseTb4b4b4:
Tff7b72selfTff7b72.Td2a8fftransport_id Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffdestination_hash Tff7b72= Tff7b72selfTff7b72.Td2a8ffrawTb4b4b4[T79c0ff2Tb4b4b4:Te6edf3DST_LENTff7b72+T79c0ff2Tb4b4b4]
Tff7b72selfTff7b72.Td2a8ffcontext Tff7b72= Tffa657ordTb4b4b4(Tff7b72selfTff7b72.Td2a8ffrawTb4b4b4[Te6edf3DST_LENTff7b72+T79c0ff2Tb4b4b4:Te6edf3DST_LENTff7b72+T79c0ff3Tb4b4b4]Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffdata Tff7b72= Tff7b72selfTff7b72.Td2a8ffrawTb4b4b4[Te6edf3DST_LENTff7b72+T79c0ff3Tb4b4b4:Tb4b4b4]

Tff7b72selfTff7b72.Td2a8ffpacked Tff7b72= Tff7b72False
Tff7b72selfTff7b72.Td2a8ffupdate_hashTb4b4b4(Tb4b4b4)
Tff7b72return Tff7b72True

Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff"Ta5d6ffReceived malformed packet, dropping it. The contained exception was: Ta5d6ff"Tff7b72+Tffa657strTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_EXTREMETb4b4b4)
Tff7b72return Tff7b72False

Tff7b72def Td2a8ffsendTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""
Sends the packet.
:returns: A :ref:`RNS.PacketReceipt<api-packetreceipt>` instance if *create_receipt* was set to *True* when the packet was instantiated, if not returns *None*. If the packet could not be sent *False* is returned.
"""
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ffsentTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8fftype Tff7b72== Te6edf3RNSTff7b72.Td2a8ffDestinationTff7b72.Td2a8ffLINKTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffstatus Tff7b72== Te6edf3RNSTff7b72.Td2a8ffLinkTff7b72.Td2a8ffCLOSEDTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff"Ta5d6ffAttempt to transmit over a closed link, dropping packetTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffsent Tff7b72= Tff7b72False
Tff7b72selfTff7b72.Td2a8ffreceipt Tff7b72= Tff7b72None
Tff7b72return Tff7b72False

Tff7b72elseTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8fflast_outbound Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8fftx Tff7b72+Tff7b72= T79c0ff1
Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8fftxbytes Tff7b72+Tff7b72= Tffa657lenTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdataTb4b4b4)

Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ffpackedTb4b4b4: Tff7b72selfTff7b72.Td2a8ffpackTb4b4b4(Tb4b4b4)

Tff7b72if Te6edf3RNSTff7b72.Td2a8ffTransportTff7b72.Td2a8ffoutboundTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4: Tff7b72return Tff7b72selfTff7b72.Td2a8ffreceipt
Tff7b72elseTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff"Ta5d6ffNo interfaces could process the outbound packetTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffsent Tff7b72= Tff7b72False
Tff7b72selfTff7b72.Td2a8ffreceipt Tff7b72= Tff7b72None
Tff7b72return Tff7b72False
Tff7b72elseTb4b4b4:
Tff7b72raise Tf85149IOErrorTb4b4b4(Ta5d6ff"Ta5d6ffPacket was already sentTa5d6ff"Tb4b4b4)

Tff7b72def Td2a8ffresendTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""
Re-sends the packet.
:returns: A :ref:`RNS.PacketReceipt<api-packetreceipt>` instance if *create_receipt* was set to *True* when the packet was instantiated, if not returns *None*. If the packet could not be sent *False* is returned.
"""
Tff7b72if Tff7b72selfTff7b72.Td2a8ffsentTb4b4b4:
T8b949e# Re-pack the packet to obtain new ciphertext for
T8b949e# encrypted destinations
Tff7b72selfTff7b72.Td2a8ffpackTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3RNSTff7b72.Td2a8ffTransportTff7b72.Td2a8ffoutboundTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffreceipt
Tff7b72elseTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff"Ta5d6ffRe-send failed. No interfaces could process the outbound packetTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_WARNINGTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffsent Tff7b72= Tff7b72False
Tff7b72selfTff7b72.Td2a8ffreceipt Tff7b72= Tff7b72None
Tff7b72return Tff7b72False
Tff7b72elseTb4b4b4:
Tff7b72raise Tf85149IOErrorTb4b4b4(Ta5d6ff"Ta5d6ffPacket was not sent yetTa5d6ff"Tb4b4b4)

Tff7b72def Td2a8ffproveTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3destinationTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8fffromPacked Tff7b72and Tffa657hasattrTb4b4b4(Tff7b72selfTb4b4b4, Ta5d6ff"Ta5d6ffdestinationTa5d6ff"Tb4b4b4) Tff7b72and Tff7b72selfTff7b72.Td2a8ffdestinationTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffidentity Tff7b72and Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffidentityTff7b72.Td2a8ffprvTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffidentityTff7b72.Td2a8ffproveTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3destinationTb4b4b4)
Tff7b72elif Tff7b72selfTff7b72.Td2a8fffromPacked Tff7b72and Tffa657hasattrTb4b4b4(Tff7b72selfTb4b4b4, Ta5d6ff"Ta5d6fflinkTa5d6ff"Tb4b4b4) Tff7b72and Tff7b72selfTff7b72.Td2a8fflinkTb4b4b4:
Tff7b72selfTff7b72.Td2a8fflinkTff7b72.Td2a8ffprove_packetTb4b4b4(Tff7b72selfTb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff"Ta5d6ffCould not prove packet associated with neither a destination nor a linkTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)

T8b949e# Generates a special destination that allows Reticulum
T8b949e# to direct the proof back to the proved packet's sender
Tff7b72def Td2a8ffgenerate_proof_destinationTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3ProofDestinationTb4b4b4(Tff7b72selfTb4b4b4)

Tff7b72def Td2a8ffvalidate_proof_packetTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3proof_packetTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffreceiptTff7b72.Td2a8ffvalidate_proof_packetTb4b4b4(Te6edf3proof_packetTb4b4b4)

Tff7b72def Td2a8ffvalidate_proofTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3proofTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffreceiptTff7b72.Td2a8ffvalidate_proofTb4b4b4(Te6edf3proofTb4b4b4)

Tff7b72def Td2a8ffupdate_hashTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffpacket_hash Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_hashTb4b4b4(Tb4b4b4)

Tff7b72def Td2a8ffget_hashTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8fffull_hashTb4b4b4(Tff7b72selfTff7b72.Td2a8ffget_hashable_partTb4b4b4(Tb4b4b4)Tb4b4b4)

Tff7b72def Td2a8ffgetTruncatedHashTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8fftruncated_hashTb4b4b4(Tff7b72selfTff7b72.Td2a8ffget_hashable_partTb4b4b4(Tb4b4b4)Tb4b4b4)

Tff7b72def Td2a8ffget_hashable_partTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3hashable_part Tff7b72= Tffa657bytesTb4b4b4(Tb4b4b4[Tff7b72selfTff7b72.Td2a8ffrawTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72& T79c0ff0b00001111Tb4b4b4]Tb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ffheader_type Tff7b72== Te6edf3PacketTff7b72.Td2a8ffHEADER_2Tb4b4b4:
Te6edf3hashable_part Tff7b72+Tff7b72= Tff7b72selfTff7b72.Td2a8ffrawTb4b4b4[Tb4b4b4(Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8ffTRUNCATED_HASHLENGTHTff7b72/Tff7b72/T79c0ff8Tb4b4b4)Tff7b72+T79c0ff2Tb4b4b4:Tb4b4b4]
Tff7b72elseTb4b4b4:
Te6edf3hashable_part Tff7b72+Tff7b72= Tff7b72selfTff7b72.Td2a8ffrawTb4b4b4[T79c0ff2Tb4b4b4:Tb4b4b4]

Tff7b72return Te6edf3hashable_part

Tff7b72def Td2a8ffget_rssiTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""
:returns: The physical layer *Received Signal Strength Indication* if available, otherwise ``None``.
"""
Tff7b72if Tff7b72selfTff7b72.Td2a8ffrssi Tff7b72!= Tff7b72NoneTb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffrssi
Tff7b72elseTb4b4b4:
Tff7b72return Te6edf3reticulumTff7b72.Td2a8ffget_packet_rssiTb4b4b4(Tff7b72selfTff7b72.Td2a8ffpacket_hashTb4b4b4)
Tff7b72def Td2a8ffget_snrTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""
:returns: The physical layer *Signal-to-Noise Ratio* if available, otherwise ``None``.
"""
Tff7b72if Tff7b72selfTff7b72.Td2a8ffsnr Tff7b72!= Tff7b72NoneTb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffsnr
Tff7b72elseTb4b4b4:
Tff7b72return Te6edf3reticulumTff7b72.Td2a8ffget_packet_snrTb4b4b4(Tff7b72selfTff7b72.Td2a8ffpacket_hashTb4b4b4)

Tff7b72def Td2a8ffget_qTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""
:returns: The physical layer *Link Quality* if available, otherwise ``None``.
"""
Tff7b72if Tff7b72selfTff7b72.Td2a8ffq Tff7b72!= Tff7b72NoneTb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffq
Tff7b72elseTb4b4b4:
Tff7b72return Te6edf3reticulumTff7b72.Td2a8ffget_packet_qTb4b4b4(Tff7b72selfTff7b72.Td2a8ffpacket_hashTb4b4b4)

Tff7b72class T56d364ProofDestinationTb4b4b4:
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3packetTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffhash Tff7b72= Te6edf3packetTff7b72.Td2a8ffget_hashTb4b4b4(Tb4b4b4)Tb4b4b4[Tb4b4b4:Te6edf3RNSTff7b72.Td2a8ffReticulumTff7b72.Td2a8ffTRUNCATED_HASHLENGTHTff7b72/Tff7b72/T79c0ff8Tb4b4b4]Tb4b4b4;
Tff7b72selfTff7b72.Td2a8fftype Tff7b72= Te6edf3RNSTff7b72.Td2a8ffDestinationTff7b72.Td2a8ffSINGLE

Tff7b72def Td2a8ffencryptTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3plaintextTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3plaintext


Tff7b72class T56d364PacketReceiptTb4b4b4:
T8b949e"""
The PacketReceipt class is used to receive notifications about
:ref:`RNS.Packet<api-packet>` instances sent over the network. Instances
of this class are never created manually, but always returned from
the *send()* method of a :ref:`RNS.Packet<api-packet>` instance.
"""
T8b949e# Receipt status constants
Te6edf3FAILED Tff7b72= T79c0ff0x00
Te6edf3SENT Tff7b72= T79c0ff0x01
Te6edf3DELIVERED Tff7b72= T79c0ff0x02
Te6edf3CULLED Tff7b72= T79c0ff0xFF


Te6edf3EXPL_LENGTH Tff7b72= Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8ffHASHLENGTHTff7b72/Tff7b72/T79c0ff8Tff7b72+Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8ffSIGLENGTHTff7b72/Tff7b72/T79c0ff8
Te6edf3IMPL_LENGTH Tff7b72= Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8ffSIGLENGTHTff7b72/Tff7b72/T79c0ff8

T8b949e# Creates a new packet receipt from a sent packet
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3packetTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffhash Tff7b72= Te6edf3packetTff7b72.Td2a8ffget_hashTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8fftruncated_hash Tff7b72= Te6edf3packetTff7b72.Td2a8ffgetTruncatedHashTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffsent Tff7b72= Tff7b72True
Tff7b72selfTff7b72.Td2a8ffsent_at Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffproved Tff7b72= Tff7b72False
Tff7b72selfTff7b72.Td2a8ffstatus Tff7b72= Te6edf3PacketReceiptTff7b72.Td2a8ffSENT
Tff7b72selfTff7b72.Td2a8ffdestination Tff7b72= Te6edf3packetTff7b72.Td2a8ffdestination
Tff7b72selfTff7b72.Td2a8ffcallbacks Tff7b72= Te6edf3PacketReceiptCallbacksTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffconcluded_at Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffproof_packet Tff7b72= Tff7b72None

Tff7b72if Te6edf3packetTff7b72.Td2a8ffdestinationTff7b72.Td2a8fftype Tff7b72== Te6edf3RNSTff7b72.Td2a8ffDestinationTff7b72.Td2a8ffLINKTb4b4b4:
Tff7b72selfTff7b72.Td2a8fftimeout Tff7b72= Tffa657maxTb4b4b4(Te6edf3packetTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffrtt Tff7b72* Te6edf3packetTff7b72.Td2a8ffdestinationTff7b72.Td2a8fftraffic_timeout_factorTb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLinkTff7b72.Td2a8ffTRAFFIC_TIMEOUT_MIN_MSTff7b72/T79c0ff1000Tb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72selfTff7b72.Td2a8fftimeout Tff7b72= Te6edf3RNSTff7b72.Td2a8ffReticulumTff7b72.Td2a8ffget_instanceTb4b4b4(Tb4b4b4)Tff7b72.Td2a8ffget_first_hop_timeoutTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffhashTb4b4b4)
Tff7b72selfTff7b72.Td2a8fftimeout Tff7b72+Tff7b72= Te6edf3PacketTff7b72.Td2a8ffTIMEOUT_PER_HOP Tff7b72* Te6edf3RNSTff7b72.Td2a8ffTransportTff7b72.Td2a8ffhops_toTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffhashTb4b4b4)

Tff7b72def Td2a8ffget_statusTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""
:returns: The status of the associated :ref:`RNS.Packet<api-packet>` instance. Can be one of ``RNS.PacketReceipt.SENT``, ``RNS.PacketReceipt.DELIVERED``, ``RNS.PacketReceipt.FAILED`` or ``RNS.PacketReceipt.CULLED``.
"""
Tff7b72return Tff7b72selfTff7b72.Td2a8ffstatus

T8b949e# Validate a proof packet
Tff7b72def Td2a8ffvalidate_proof_packetTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3proof_packetTb4b4b4)Tb4b4b4:
Tff7b72if Tffa657hasattrTb4b4b4(Te6edf3proof_packetTb4b4b4, Ta5d6ff"Ta5d6fflinkTa5d6ff"Tb4b4b4) Tff7b72and Te6edf3proof_packetTff7b72.Td2a8fflinkTb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffvalidate_link_proofTb4b4b4(Te6edf3proof_packetTff7b72.Td2a8ffdataTb4b4b4, Te6edf3proof_packetTff7b72.Td2a8fflinkTb4b4b4, Te6edf3proof_packetTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffvalidate_proofTb4b4b4(Te6edf3proof_packetTff7b72.Td2a8ffdataTb4b4b4, Te6edf3proof_packetTb4b4b4)

T8b949e# Validate a raw proof for a link
Tff7b72def Td2a8ffvalidate_link_proofTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3proofTb4b4b4, Te6edf3linkTb4b4b4, Te6edf3proof_packetTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
T8b949e# TODO: Hardcoded as explicit proofs for now
Tff7b72if Tff7b72True Tff7b72or Tffa657lenTb4b4b4(Te6edf3proofTb4b4b4) Tff7b72== Te6edf3PacketReceiptTff7b72.Td2a8ffEXPL_LENGTHTb4b4b4:
T8b949e# This is an explicit proof
Te6edf3proof_hash Tff7b72= Te6edf3proofTb4b4b4[Tb4b4b4:Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8ffHASHLENGTHTff7b72/Tff7b72/T79c0ff8Tb4b4b4]
Te6edf3signature Tff7b72= Te6edf3proofTb4b4b4[Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8ffHASHLENGTHTff7b72/Tff7b72/T79c0ff8Tb4b4b4:Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8ffHASHLENGTHTff7b72/Tff7b72/T79c0ff8Tff7b72+Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8ffSIGLENGTHTff7b72/Tff7b72/T79c0ff8Tb4b4b4]
Tff7b72if Te6edf3proof_hash Tff7b72== Tff7b72selfTff7b72.Td2a8ffhashTb4b4b4:
Te6edf3proof_valid Tff7b72= Te6edf3linkTff7b72.Td2a8ffvalidateTb4b4b4(Te6edf3signatureTb4b4b4, Tff7b72selfTff7b72.Td2a8ffhashTb4b4b4)
Tff7b72if Te6edf3proof_validTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffstatus Tff7b72= Te6edf3PacketReceiptTff7b72.Td2a8ffDELIVERED
Tff7b72selfTff7b72.Td2a8ffproved Tff7b72= Tff7b72True
Tff7b72selfTff7b72.Td2a8ffconcluded_at Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffproof_packet Tff7b72= Te6edf3proof_packet
Te6edf3linkTff7b72.Td2a8fflast_proof Tff7b72= Tff7b72selfTff7b72.Td2a8ffconcluded_at

Tff7b72if Tff7b72selfTff7b72.Td2a8ffcallbacksTff7b72.Td2a8ffdelivery Tff7b72!= Tff7b72NoneTb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffcallbacksTff7b72.Td2a8ffdeliveryTb4b4b4(Tff7b72selfTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff"Ta5d6ffAn error occurred while evaluating external delivery callback for Ta5d6ff"Tff7b72+Tffa657strTb4b4b4(Te6edf3linkTb4b4b4)Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff"Ta5d6ffThe contained exception was: Ta5d6ff"Tff7b72+Tffa657strTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Te6edf3RNSTff7b72.Td2a8fftrace_exceptionTb4b4b4(Te6edf3eTb4b4b4)
Tff7b72return Tff7b72True
Tff7b72elseTb4b4b4:
Tff7b72return Tff7b72False
Tff7b72elseTb4b4b4:
Tff7b72return Tff7b72False
Tff7b72elif Tffa657lenTb4b4b4(Te6edf3proofTb4b4b4) Tff7b72== Te6edf3PacketReceiptTff7b72.Td2a8ffIMPL_LENGTHTb4b4b4:
Tff7b72pass
T8b949e# TODO: Why is this disabled?
T8b949e# signature = proof[:RNS.Identity.SIGLENGTH//8]
T8b949e# proof_valid = self.link.validate(signature, self.hash)
T8b949e# if proof_valid:
T8b949e# self.status = PacketReceipt.DELIVERED
T8b949e# self.proved = True
T8b949e# self.concluded_at = time.time()
T8b949e# if self.callbacks.delivery != None:
T8b949e# self.callbacks.delivery(self)
T8b949e# RNS.log("valid")
T8b949e# return True
T8b949e# else:
T8b949e# RNS.log("invalid")
T8b949e# return False
Tff7b72elseTb4b4b4:
Tff7b72return Tff7b72False

T8b949e# Validate a raw proof
Tff7b72def Td2a8ffvalidate_proofTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3proofTb4b4b4, Te6edf3proof_packetTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
Tff7b72if Tffa657lenTb4b4b4(Te6edf3proofTb4b4b4) Tff7b72== Te6edf3PacketReceiptTff7b72.Td2a8ffEXPL_LENGTHTb4b4b4:
T8b949e# This is an explicit proof
Te6edf3proof_hash Tff7b72= Te6edf3proofTb4b4b4[Tb4b4b4:Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8ffHASHLENGTHTff7b72/Tff7b72/T79c0ff8Tb4b4b4]
Te6edf3signature Tff7b72= Te6edf3proofTb4b4b4[Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8ffHASHLENGTHTff7b72/Tff7b72/T79c0ff8Tb4b4b4:Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8ffHASHLENGTHTff7b72/Tff7b72/T79c0ff8Tff7b72+Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8ffSIGLENGTHTff7b72/Tff7b72/T79c0ff8Tb4b4b4]
Tff7b72if Te6edf3proof_hash Tff7b72== Tff7b72selfTff7b72.Td2a8ffhash Tff7b72and Tffa657hasattrTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdestinationTb4b4b4, Ta5d6ff"Ta5d6ffidentityTa5d6ff"Tb4b4b4) Tff7b72and Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffidentity Tff7b72!= Tff7b72NoneTb4b4b4:
Te6edf3proof_valid Tff7b72= Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffidentityTff7b72.Td2a8ffvalidateTb4b4b4(Te6edf3signatureTb4b4b4, Tff7b72selfTff7b72.Td2a8ffhashTb4b4b4)
Tff7b72if Te6edf3proof_validTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffstatus Tff7b72= Te6edf3PacketReceiptTff7b72.Td2a8ffDELIVERED
Tff7b72selfTff7b72.Td2a8ffproved Tff7b72= Tff7b72True
Tff7b72selfTff7b72.Td2a8ffconcluded_at Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffproof_packet Tff7b72= Te6edf3proof_packet

Tff7b72if Tff7b72selfTff7b72.Td2a8ffcallbacksTff7b72.Td2a8ffdelivery Tff7b72!= Tff7b72NoneTb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffcallbacksTff7b72.Td2a8ffdeliveryTb4b4b4(Tff7b72selfTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff"Ta5d6ffError while executing proof validated callback. The contained exception was: Ta5d6ff"Tff7b72+Tffa657strTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)

Tff7b72return Tff7b72True
Tff7b72elseTb4b4b4:
Tff7b72return Tff7b72False
Tff7b72elseTb4b4b4:
Tff7b72return Tff7b72False
Tff7b72elif Tffa657lenTb4b4b4(Te6edf3proofTb4b4b4) Tff7b72== Te6edf3PacketReceiptTff7b72.Td2a8ffIMPL_LENGTHTb4b4b4:
T8b949e# This is an implicit proof

Tff7b72if Tff7b72not Tffa657hasattrTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdestinationTb4b4b4, Ta5d6ff"Ta5d6ffidentityTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72False

Tff7b72if Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffidentity Tff7b72== Tff7b72NoneTb4b4b4:
Tff7b72return Tff7b72False

Te6edf3signature Tff7b72= Te6edf3proofTb4b4b4[Tb4b4b4:Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8ffSIGLENGTHTff7b72/Tff7b72/T79c0ff8Tb4b4b4]
Te6edf3proof_valid Tff7b72= Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffidentityTff7b72.Td2a8ffvalidateTb4b4b4(Te6edf3signatureTb4b4b4, Tff7b72selfTff7b72.Td2a8ffhashTb4b4b4)
Tff7b72if Te6edf3proof_validTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffstatus Tff7b72= Te6edf3PacketReceiptTff7b72.Td2a8ffDELIVERED
Tff7b72selfTff7b72.Td2a8ffproved Tff7b72= Tff7b72True
Tff7b72selfTff7b72.Td2a8ffconcluded_at Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffproof_packet Tff7b72= Te6edf3proof_packet

Tff7b72if Tff7b72selfTff7b72.Td2a8ffcallbacksTff7b72.Td2a8ffdelivery Tff7b72!= Tff7b72NoneTb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffcallbacksTff7b72.Td2a8ffdeliveryTb4b4b4(Tff7b72selfTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff"Ta5d6ffError while executing proof validated callback. The contained exception was: Ta5d6ff"Tff7b72+Tffa657strTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Tff7b72return Tff7b72True
Tff7b72elseTb4b4b4:
Tff7b72return Tff7b72False
Tff7b72elseTb4b4b4:
Tff7b72return Tff7b72False

Tff7b72def Td2a8ffget_rttTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""
:returns: The round-trip-time in seconds
"""
Tff7b72return Tff7b72selfTff7b72.Td2a8ffconcluded_at Tff7b72- Tff7b72selfTff7b72.Td2a8ffsent_at

Tff7b72def Td2a8ffis_timed_outTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffsent_atTff7b72+Tff7b72selfTff7b72.Td2a8fftimeout Tff7b72< Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)Tb4b4b4)

Tff7b72def Td2a8ffcheck_timeoutTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffstatus Tff7b72== Te6edf3PacketReceiptTff7b72.Td2a8ffSENT Tff7b72and Tff7b72selfTff7b72.Td2a8ffis_timed_outTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8fftimeout Tff7b72== Tff7b72-T79c0ff1Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffstatus Tff7b72= Te6edf3PacketReceiptTff7b72.Td2a8ffCULLED
Tff7b72elseTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffstatus Tff7b72= Te6edf3PacketReceiptTff7b72.Td2a8ffFAILED

Tff7b72selfTff7b72.Td2a8ffconcluded_at Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)

Tff7b72if Tff7b72selfTff7b72.Td2a8ffcallbacksTff7b72.Td2a8fftimeoutTb4b4b4:
Te6edf3thread Tff7b72= Te6edf3threadingTff7b72.Td2a8ffThreadTb4b4b4(Te6edf3targetTff7b72=Tff7b72selfTff7b72.Td2a8ffcallbacksTff7b72.Td2a8fftimeoutTb4b4b4, Te6edf3argsTff7b72=Tb4b4b4(Tff7b72selfTb4b4b4,Tb4b4b4)Tb4b4b4)
Te6edf3threadTff7b72.Td2a8ffdaemon Tff7b72= Tff7b72True
Te6edf3threadTff7b72.Td2a8ffstartTb4b4b4(Tb4b4b4)


Tff7b72def Td2a8ffset_timeoutTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3timeoutTb4b4b4)Tb4b4b4:
T8b949e"""
Sets a timeout in seconds
:param timeout: The timeout in seconds.
"""
Tff7b72selfTff7b72.Td2a8fftimeout Tff7b72= Tffa657floatTb4b4b4(Te6edf3timeoutTb4b4b4)

Tff7b72def Td2a8ffset_delivery_callbackTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3callbackTb4b4b4)Tb4b4b4:
T8b949e"""
Sets a function that gets called if a successfull delivery has been proven.

:param callback: A *callable* with the signature *callback(packet_receipt)*
"""
Tff7b72selfTff7b72.Td2a8ffcallbacksTff7b72.Td2a8ffdelivery Tff7b72= Te6edf3callback

T8b949e# Set a function that gets called if the
T8b949e# delivery times out
Tff7b72def Td2a8ffset_timeout_callbackTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3callbackTb4b4b4)Tb4b4b4:
T8b949e"""
Sets a function that gets called if the delivery times out.

:param callback: A *callable* with the signature *callback(packet_receipt)*
"""
Tff7b72selfTff7b72.Td2a8ffcallbacksTff7b72.Td2a8fftimeout Tff7b72= Te6edf3callback

Tff7b72class T56d364PacketReceiptCallbacksTb4b4b4:
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffdelivery Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8fftimeout Tff7b72= Tff7b72None


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────